package com.codedancer.campus.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codedancer.campus.client.service.ICircleService;
import com.codedancer.campus.client.service.bo.circle.CircleCreateBo;
import com.codedancer.campus.client.service.bo.circle.CirclePageSearchBo;
import com.codedancer.campus.client.service.vo.circle.CirclePageVo;
import com.codedancer.campus.client.service.vo.circle.CircleVo;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.UUIDGenerator;
import com.codedancer.campus.enums.CircleStatus;
import com.codedancer.campus.mapper.CircleFollowMapper;
import com.codedancer.campus.mapper.CircleLabelMapper;
import com.codedancer.campus.mapper.CircleMapper;
import com.codedancer.campus.mapper.DynamicMapper;
import com.codedancer.campus.mapper.UserSchoolMapper;
import com.codedancer.campus.po.Circle;
import com.codedancer.campus.po.CircleFollow;
import com.codedancer.campus.po.CircleLabel;
import com.codedancer.campus.po.UserSchool;
import com.codedancer.campus.qo.circle.CirclePageSearchQo;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor = Exception.class)
public class CircleServiceImpl implements ICircleService {

  @Autowired
  private CircleMapper circleMapper;
  @Autowired
  private UserSchoolMapper userSchoolMapper;
  @Autowired
  private CircleFollowMapper circleFollowMapper;
  @Autowired
  private CircleLabelMapper circleLabelMapper;
  @Autowired
  private DynamicMapper dynamicMapper;

  /**
   * 创建圈子
   *
   * @param circleCreateBo
   */
  @Override
  public void create(CircleCreateBo circleCreateBo) {
    UserSchool userSchool = userSchoolMapper
        .selectOneByColumn("user_uuid", circleCreateBo.getCurrentUserUuid());
    if (CollectionUtil.isEmpty(circleCreateBo.getLabels())
        || circleCreateBo.getLabels().size() < 5) {
      throw new BusinessException("请至少填写五个标签");
    }
    // 判断该学校圈子标题是否存在
    if (circleMapper
        .existsBySchoolUuidAndName(userSchool.getSchoolUuid(), circleCreateBo.getTitle())) {
      throw new BusinessException("圈子名称已存在，请重新填写");
    }
    Circle circle = BeanUtil.copyProperties(circleCreateBo, Circle.class);
    circle.setUuid(UUIDGenerator.getUUID());
    circle.setStatus(CircleStatus.PENDING_REVIEW);
    circle.setCreateUserUuid(circleCreateBo.getCurrentUserUuid());
    circle.setCreateSchoolUuid(userSchool.getSchoolUuid());
    circleMapper.insert(circle);
    // 先判断是否存在重复标签
    long distinctCount = circleCreateBo.getLabels().stream().distinct().count();
    if (distinctCount != circleCreateBo.getLabels().size()) {
      throw new BusinessException("存在重复标签，请重新填写");
    }
    // 保存标签
    for (String label : circleCreateBo.getLabels()) {
      CircleLabel circleLabel = CircleLabel.builder()
          .uuid(UUIDGenerator.getUUID())
          .circleUuid(circle.getUuid())
          .name("#" + label).build();
      circleLabelMapper.insert(circleLabel);
    }
  }

  /**
   * 查询圈子排名前十
   *
   * @param currentUserUuid
   * @return
   */
  @Override
  public List<CircleVo>
  top10(String currentUserUuid) {
    UserSchool userSchool = userSchoolMapper
        .selectOneByColumn("user_uuid", currentUserUuid);
    List<Circle> circles = circleMapper.top10OrderByFollowCount(userSchool.getSchoolUuid());
    List<CircleVo> circleVos;
    circleVos = circles.stream().map(circle -> {
      CircleVo circleVo = BeanUtil.copyProperties(circle, CircleVo.class);
      // 判断当前用户是否关注
      circleVo
          .setIsFollow(circleFollowMapper.isFollow(circle.getUuid(), currentUserUuid));
      return circleVo;
    }).collect(Collectors.toList());
    return circleVos;
  }

  /**
   * 关注圈子
   *
   * @param uuid
   */
  @Override
  public void follow(String uuid, String currentUserUuid) {
    Circle circle = circleMapper.findById(uuid)
        .orElseThrow(() -> new BusinessException("圈子不存在"));
    // 判断是否已关注
    if (circleFollowMapper.isFollow(uuid, currentUserUuid)) {
      throw new BusinessException("不能重复关注");
    }
    CircleFollow circleFollow = CircleFollow.builder()
        .circleUuid(uuid)
        .followUserUuid(currentUserUuid)
        .build();
    circleFollowMapper.insert(circleFollow);
    // 圈子关注量加1
    circle.setFollowCount(circle.getFollowCount() + 1);
    circleMapper.updateById(circle);
  }

  /**
   * 取消关注
   *
   * @param uuid
   * @param currentLoginUuid
   */
  @Override
  public void cancelFollow(String uuid, String currentLoginUuid) {
    Circle circle = circleMapper.findById(uuid)
        .orElseThrow(() -> new BusinessException("圈子不存在"));
    circleFollowMapper.cancelFollow(uuid, currentLoginUuid);
    // 关注数量减1
    circle.setFollowCount(circle.getFollowCount() - 1);
    circleMapper.updateById(circle);
  }

  /**
   * 分页查询圈子
   *
   * @param circlePageSearchBo
   * @return
   */
  @Override
  public IPage<CirclePageVo> page(CirclePageSearchBo circlePageSearchBo) {
    CirclePageSearchQo circlePageSearchQo = BeanUtil
        .copyProperties(circlePageSearchBo, CirclePageSearchQo.class);
    UserSchool userSchool = userSchoolMapper
        .selectOneByColumn("user_uuid", circlePageSearchBo.getCurrentUserUuid());
    circlePageSearchQo.setSchoolUuid(userSchool.getSchoolUuid());
    IPage<Circle> circleIPage = circleMapper.pageToClient(
        new Page<Circle>(circlePageSearchBo.getPage(), circlePageSearchBo.getSize()),
        circlePageSearchQo);
    List<CirclePageVo> circlePageVos;
    IPage<CirclePageVo> circlePageVoIPage = new Page<>();
    circlePageVos = circleIPage.getRecords().stream()
        .map(circle -> {
          return BeanUtil.copyProperties(circle, CirclePageVo.class);
        }).collect(Collectors.toList());
    circlePageVoIPage.setRecords(circlePageVos);
    circlePageVoIPage.setTotal(circleIPage.getTotal());
    return circlePageVoIPage;
  }

  /**
   * 圈子详情
   *
   * @param uuid
   * @return
   */
  @Override
  public CircleVo detail(String uuid, String currentUserUuid) {
    Circle circle = circleMapper.findById(uuid)
        .orElseThrow(() -> new BusinessException("圈子不存在"));
    CircleVo circleVo = BeanUtil.copyProperties(circle, CircleVo.class);
    // 获取关注数
    int followCount = circleFollowMapper.countByColumn("circle_uuid", uuid);
    circleVo.setFollowCount(followCount);
    // 判断该用户是否关注
    circleVo.setIsFollow(circleFollowMapper.isFollow(uuid, currentUserUuid));
    // 根据圈子查询动态数量
    int dynamicCount = dynamicMapper.countByCircleUuid(uuid);
    circleVo.setDynamicCount(dynamicCount);
    // 获取圈子关联标签
    List<CircleLabel> circleLabels = circleLabelMapper
        .selectListByColumn("circle_uuid", circle.getUuid());
    circleVo.setCircleLabels(
        circleLabels.stream().map(CircleLabel::getName).collect(Collectors.toList()));
    return circleVo;
  }

  /**
   * 获取某个学校全部圈子
   *
   * @return
   */
  @Override
  public List<CircleVo> listBySchoolUuid(String currentUserUuid) {
    UserSchool userSchool = userSchoolMapper
        .selectOneByColumn("user_uuid", currentUserUuid);
    List<Circle> circles = circleMapper.listBySchoolUuid(userSchool.getSchoolUuid());
    return circles.stream().map(circle -> BeanUtil.copyProperties(circle, CircleVo.class))
        .collect(Collectors.toList());
  }

  /**
   * 分页查询用户关注或创建的圈子
   *
   * @param circlePageSearchBo
   * @return
   */
  @Override
  public IPage<CirclePageVo> page2User(CirclePageSearchBo circlePageSearchBo) {
    CirclePageSearchQo circlePageSearchQo = BeanUtil
        .copyProperties(circlePageSearchBo, CirclePageSearchQo.class);
    if (ObjectUtil.isEmpty(circlePageSearchBo.getType())) {
      throw new BusinessException("查询类型不能为空");
    }
    List<CirclePageVo> circlePageVos = null;
    IPage<CirclePageVo> circlePageVoIPage = new Page<>();
    if (circlePageSearchBo.getType().equals("follow")) {
      // 查询关注的圈子
      IPage<CircleFollow> circleFollowIPage = circleFollowMapper.pageFollow(
          new Page<CircleFollow>(circlePageSearchBo.getPage(), circlePageSearchBo.getSize()),
          circlePageSearchQo);
      circlePageVos = circleFollowIPage.getRecords().stream().map(circleFollow -> {
        // 查询圈子
        Circle circle = circleMapper.selectById(circleFollow.getCircleUuid());
        return BeanUtil.copyProperties(circle, CirclePageVo.class);
      }).collect(Collectors.toList());
    }
    if (circlePageSearchBo.getType().equals("create")) {
      // 查询我创建的圈子
      IPage<Circle> circleIPage = circleMapper
          .pageCreate(
              new Page<Circle>(circlePageSearchBo.getPage(), circlePageSearchBo.getSize()),
              circlePageSearchQo);
      circlePageVos = circleIPage.getRecords().stream()
          .map(circle -> BeanUtil.copyProperties(circle, CirclePageVo.class))
          .collect(Collectors.toList());
    }
    circlePageVoIPage.setRecords(circlePageVos);
    return circlePageVoIPage;
  }

  /**
   * 启用圈子
   *
   * @param uuid
   */
  @Override
  public void enable(String uuid) {
    Circle circle = circleMapper.findById(uuid)
        .orElseThrow(() -> new BusinessException("圈子不存在"));
    circle.setDisabled(false);
    circleMapper.updateById(circle);
  }

  /**
   * 禁用圈子
   *
   * @param uuid
   */
  @Override
  public void disable(String uuid) {
    Circle circle = circleMapper.findById(uuid)
        .orElseThrow(() -> new BusinessException("圈子不存在"));
    circle.setDisabled(true);
    circleMapper.updateById(circle);
  }

  /**
   * 删除圈子
   *
   * @param uuid
   */
  @Override
  public void delete(String uuid) {
    // 删除圈子关联的数据信息
    // 删除用户关注的圈子
    circleFollowMapper.deleteByColumn("circle_uuid", uuid);
    circleMapper.deleteById(uuid);
  }

  /**
   * 修改圈子
   *
   * @param circleCreateBo
   */
  @Override
  public void update(CircleCreateBo circleCreateBo) {
    Circle circle = circleMapper.findById(circleCreateBo.getUuid())
        .orElseThrow(() -> new BusinessException("圈子不存在"));
    if (CollectionUtil.isEmpty(circleCreateBo.getLabels())
        || circleCreateBo.getLabels().size() < 5) {
      throw new BusinessException("请至少填写五个标签");
    }
    UserSchool userSchool = userSchoolMapper
        .selectOneByColumn("user_uuid", circleCreateBo.getCurrentUserUuid());
    // 判断该学校圈子标题是否存在
    if (!circle.getTitle().equals(circleCreateBo.getTitle())) {
      if (circleMapper
          .existsBySchoolUuidAndName(userSchool.getSchoolUuid(), circleCreateBo.getTitle())) {
        throw new BusinessException("圈子名称已存在，请重新填写");
      }
    }
    // 先判断是否存在重复标签
    long distinctCount = circleCreateBo.getLabels().stream().distinct().count();
    if (distinctCount != circleCreateBo.getLabels().size()) {
      throw new BusinessException("存在重复标签，请重新填写");
    }
    BeanUtil.copyProperties(circleCreateBo, circle);
    circle.setStatus(CircleStatus.PENDING_REVIEW);
    circleMapper.updateById(circle);
    // 先删除关联的标签
    circleLabelMapper.deleteByColumn("circle_uuid", circle.getUuid());
    // 保存标签
    for (String label : circleCreateBo.getLabels()) {
      CircleLabel circleLabel = CircleLabel.builder()
          .uuid(UUIDGenerator.getUUID())
          .circleUuid(circle.getUuid())
          .name("#" + label).build();
      circleLabelMapper.insert(circleLabel);
    }
  }
}
